import {PluginCommand} from "../../../Command/PluginCommand";
import {PluginCADToolFunctionType, PluginFunctionType} from "../../../../nodeApp/static/lib/crowncad-plugin-sdk-0.0.1";
import {request} from "../../../util/Request";
import {ElementType} from "../../../modeling/TypeDefine";

class SeparationFaceCommand extends PluginCommand {
  constructor() {
    super();
    /**
     * 项目编码
     * @type {string}
     */
    this.projectId = "";
    /**
     * 文档编码
     * @type {string}
     */
    this.activeDocId = "";
    /**
     * 工作空间模式
     * @type {string}
     */
    this.workSpaceMode = "PartDocument";
    /**
     * 高亮表格行id
     * @type {number}
     */
    this.highLightId = 0;
    /**
     * 分离面数据
     * @type {*[]}
     */
    this.separationList = [];
    /**
     * 装配下的实例数据
     * @type {*[]}
     */
    this.instancesProtoDatas = [];
  }

  handlePickFaceInfo(types, cb){
    this.setSelectType(types);
    this.event.subscribeElementPickEvent(e =>
      this.toolQuery.getPickFaceInfo().then(res =>{
        cb(res?.data)
      })
    )
  }

  /**
   * 获取工作空间模式
   * @param params
   * @returns {Promise<unknown> | undefined}
   */
  getWorkSpaceMode(params) {
    return this.request?.execFunction(PluginCADToolFunctionType.GETWORKSPACEMODE, {params})
      .then(res => {
        if (res.code === 200) {
          this.workSpaceMode = res.data.workspaceMode
        }
      })
  }

  /**
   * 获取项目信息
   * @returns {Promise<unknown> | undefined}
   */
  getProjectInfo() {
    return this.request?.execFunction(PluginCADToolFunctionType.GETPROJECTINFO, {}).then(res => {
      if (res && res.code === 200) {
        this.projectId = res.data?.projectInfo?.projectId;
        this.activeDocId = res.data?.projectInfo?.activeDocId
      }
    })
  }

  /**
   * 获取元素信息
   * @param id
   * @param cb
   * @returns {Promise<any>}
   */
  getElementById(id, cb) {
    return this.query.getElementsByIds([id]).then(res =>{
      if(res.code === 200){
        cb(res.data.elements);
      }
    });
  }

  /**
   * 装配模式下显隐实例的分离面数据
   * @param docId
   * @param featureId
   * @param visible
   */
  visiableFeature(docId, featureId, visible) {
    this.request.execFunction(PluginCADToolFunctionType.VISIBLEFEATURE, {docId, featureId, visible}).then()
  }

  /**
   * 界面元素拾取信息
   * @param cb
   */
  handlePickFace(cb) {
    handlePickFaceInfo([ElementType.FACE, ElementType.DATUMPLANE],
        elements => cb(elements))
  }

  /**
   * 通过表格行信息来高亮元素
   * @param isHighLight
   * @param id
   * @param docId
   * @param featureId
   * @param instanceId
   */
  hightLightElement(isHighLight, id, docId, featureId, instanceId) {
    super.clearHighLightElements([this.highLightId]);
    if (isHighLight) {
      // 如果是装配模式，区分高亮的内容
      if (this.activeDocId === docId) {
        super.highLightElements([id]);
        this.highLightId = id;
      } else {
        // 高亮具体的特征
        this.request.execFunction(PluginCADToolFunctionType.SELECTINSTANCEFEATURE,
          {instanceId, featureId}).then(res => {
        })
      }
    }
  }

  /**
   * 获取特征数据
   * @returns {Promise<any>}
   */
  async getAllFeatures() {
    return await this.request.execFunction(PluginCADToolFunctionType.GETALLFEATURES, {}).then(res => {
      if (res.code === 200) {
        return res.data;
      } else {
        return []
      }
    })
  }

  /**
   * 删除特征数据
   * @param fids 特征id
   * @param ids 分离面数据id
   * @param addCb 回调函数
   * @returns {Promise<any>}
   */
  async deleteFeatures(fid, id, operate, addCb) {
    // 先删除关联特征和数据
    let delData = this.separationList.find(s => s.id === id);
    if (delData) {
      let targetList = [];
      this.getRelatedData([delData.entityId], targetList)
      if (targetList && targetList.length) {
        let fids = targetList.map(s => s.featureId).join(",");
        let ids = targetList.map(s => s.id).join(",");
        await this.request.execFunction(PluginCADToolFunctionType.DELETEFEATURES, [fids]);
        await this.deleteSeparationSurfaces([ids])
      }
    }
    // 删除主数据
    await this.request.execFunction(PluginCADToolFunctionType.DELETEFEATURES, [fid]);
    return this.deleteSeparationSurfaces([id]).then(() => addCb?.());
  }

  /**
   * 递归查询要删除的数据
   * @param entityIds
   * @param targetList
   * @returns {*}
   */
  getRelatedData(entityIds, targetList) {
    let relatedData = this.separationList.filter(s => entityIds.indexOf(s.fromId) > -1);
    if (relatedData && relatedData.length) {
      targetList.push(...relatedData);
      let nextEntityIds = relatedData.map(s => s.entityId).join(",");
      this.getRelatedData(nextEntityIds, targetList)
    }
    return targetList;
  }

  /**
   * 增加分离面数据
   * @param surfaceName 分离面名称
   * @param createParam 命令参数
   * @param featureId 生成的特征id
   * @param entityId  实体数据id
   * @param surfaceType 分离面类型
   * @param fromId  选择面id
   * @param surfaceIndex  分离面顺序
   * @returns {Promise<AxiosResponse<any>>}
   */
  addSeparationSurface(surfaceName, createParam, featureId, entityId, surfaceType, fromId, surfaceIndex) {
    let url = "separationSurface/addSeparationSurface";
    let data = {
      projectId: this.projectId,
      activeDocId: this.activeDocId,
      surfaceName,
      featureId,
      entityId,
      surfaceType,
      fromId,
      createParam,
      surfaceIndex
    };
    let config = {
      timeout: 5000,
    };
    return request.post(url, data, config).then(res => {
    }).catch(error => {
      console.log(error)
    })
  }

  /**
   * 获取分离面数据
   * @returns {Promise<AxiosResponse<any>>}
   */
  async getSeparationSurfaces() {
    // 装配模式下获取全部实例数据
    let assemblyIds = new Set();
    if (this.workSpaceMode === "AssemblyDocument") {
      let retData = await this.request.execFunction(PluginCADToolFunctionType.GETINSTANCESPROTODATA, {});
      if(retData.code === 200){
        this.instancesProtoDatas = retData.data;
        this.instancesProtoDatas.protoData.forEach(d => {
          assemblyIds.add(d.docId);
        })
      }
    }

    // 获取当前文档的所有特征
    let features = await this.getAllFeatures();
    // 获取当前文档内所有的分离面数据
    let url = "separationSurface/getSeparationSurfaces";
    let data = new FormData();
    data.append("projectId", this.projectId);
    data.append("activeDocId", this.activeDocId);
    data.append("assemblyIds", Array.from(assemblyIds));
    let config = {
      timeout: 2000,
    };
    return request.post(url, data, config).then(res => {
      if (res.status === 200 && res.data.code === 200) {
        this.separationList = [];
        let resData = res.data.data;
        resData = resData.filter(data => features.find(f => f.name === data.surfaceName)
          || data.activeDocId !== this.activeDocId);
        // 删除不存在的数据，装配下不能删除其它零件id，需要通过docId进行区分
        let delData = res.data.data.filter(data =>
          !features.find(f => f.name === data.surfaceName) && data.activeDocId === this.activeDocId);
        if (delData && delData.length) {
          let delIds = delData.map(data => data.id).join(',');
          this.deleteSeparationSurfaces(delIds);
        }
        resData.forEach(data => {
          data.docType = "Edit"
          if (data.activeDocId !== this.activeDocId && this.workSpaceMode === "AssemblyDocument") {
            data.docType = "unEdit";
          }
          // 处理行数据
          if (this.workSpaceMode !== "AssemblyDocument" || data.activeDocId === this.activeDocId) {
            data.visible = true;
            this.separationList.push(data)
          } else {
            // 拆分数据
            this.instancesProtoDatas.protoData.forEach(pd => {
              if (pd.docId === data.activeDocId) {
                let feature = pd.features.find(f => f.featureId === data.featureId);
                if (!!feature) {
                  data.visible = feature.visible;
                }
                let newData = {...data};
                newData.surfaceName = pd.name + "-" + newData.surfaceName;
                newData.instanceId = pd.id;
                this.separationList.push(newData)
              }
            })
          }
        })
      } else {
        super.eventBusAlertMsg(this.$t('message.SeparationFace.dataError'), "error")
      }
    }).catch(error => {
      console.log(error)
    })
  }

  /**
   * 删除分离面数据
   * @param ids
   * @returns {Promise<AxiosResponse<any>>}
   */
  deleteSeparationSurfaces(ids) {
    let url = "separationSurface/deleteSeparationSurfaces";
    let data = new FormData();
    data.append("delIds", ids);
    let config = {
      timeout: 2000,
    };
    return request.post(url, data, config).then(res => {

    }).catch(error => {
      console.log(error)
    })
  }
}

const separationFaceCommand = new SeparationFaceCommand();
export default separationFaceCommand;